﻿using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.Filters;
using Nasty.Core.Config;
using Nasty.Core.LoadParams;
using Nasty.Core.Registry;
using Nasty.Core.Security;
using Nasty.Core.Session;
using Nasty.Core.SuperExtension;
using Newtonsoft.Json;
using SqlSugar;
using System;
using System.Collections.Generic;
using System.Text;
using System.Text.Json;
using System.Text.Json.Serialization;
using static System.Runtime.InteropServices.JavaScript.JSType;

namespace Nasty.Core.Attributes
{

    /// <summary>
    /// 参数是ArgParams，返回值是ResultData<string>()
    /// </summary>
    public class NastySecurityAES : ActionFilterAttribute
    {
        /// <summary>
        /// 是否记录日志
        /// </summary>
        public bool IsLog { get; set; } = false;

        /// <summary>
        /// 是否记录密文
        /// </summary>
        public bool IsCipher { get; set; } = false;


        /// <summary>
        /// 请求体第三方标记
        /// 单体标记例如：Id(Id当标记)/User.Id(用户对象中Id当标记)
        /// 联合标记例如：Id,Code (使用Id和Code进行联合标记，程序会进行合并成一个字符串)
        /// </summary>
        public string RequestThirdId { get; set; } = string.Empty;

        /// <summary>
        /// 响应体第三方标记
        /// 单体标记例如：Id(Id当标记)/User.Id(用户对象中Id当标记)
        /// 联合标记例如：Id,Code (使用Id和Code进行联合标记，程序会进行合并成一个字符串)
        /// </summary>
        public string ResponseThirdId { get; set; } = string.Empty;


        /// <summary>
        /// 请求密文
        /// </summary>
        private string _requestCipher = string.Empty;

        /// <summary>
        /// 请求体 - 解密后
        /// </summary>
        private string _requestBody = string.Empty;

        // 可以通过构造函数注入服务
        public NastySecurityAES()
        {

        }

        public override void OnActionExecuting(ActionExecutingContext context)
        {
            try
            {
                context.HttpContext.Request.Body.Position = 0;
                using (var reader = new StreamReader(context.HttpContext.Request.Body,
                    Encoding.UTF8,
                    detectEncodingFromByteOrderMarks: true,
                    bufferSize: 1024,
                    leaveOpen: true))
                {
                    //得到原始boby
                    var body = reader.ReadToEndAsync().Result;

                    //得到原始参数
                    var argParams = JsonConvert.DeserializeObject<ArgParams>(body);
                    var arg = AESHelper.Decrypt(argParams?.Arg ?? string.Empty, SuperConfig.Get("Security:AES"));

                    //得到控制器方法定义的参数类型
                    var @params = context.ActionArguments.FirstOrDefault();
                    var key = @params.Key;
                    var value = @params.Value;
                    var type = value.GetType();

                    // 将body反序列化为参数类型
                    var deserializedValue = JsonConvert.DeserializeObject(arg, type);

                    // 更新Action参数
                    context.ActionArguments[key] = deserializedValue;


                    _requestCipher = body;
                    _requestBody = arg;
                }

                base.OnActionExecuting(context);
            }
            catch (Exception ex)
            {

                context.Result = new ObjectResult(new ResultData<string>()
                {
                    IsSuccess = false,
                    Data = string.Empty,
                    Message = ex.Message,
                });
                base.OnActionExecuting(context);
                return;
            }


        }

        public override void OnActionExecuted(ActionExecutedContext context)
        {
            if (context.Exception != null)
            {
                base.OnActionExecuted(context);
                return;
            }

            dynamic result = (context.Result as ObjectResult)?.Value;

            var data = result?.Data;
            var responseCipher = string.Empty;
            var responseBody = string.Empty;
            if (result != null && result.IsSuccess && data != null)
            {
                responseBody = JsonConvert.SerializeObject(data);
                responseCipher = AESHelper.Encrypt(responseBody, SuperConfig.Get("Security:AES"));
            }


            try
            {
                if (IsLog)
                {
                    var descriptor = ((Microsoft.AspNetCore.Mvc.Controllers.ControllerActionDescriptor)context.ActionDescriptor);
                    var log = NastyActionLog.CreateActionLog(descriptor, this.RequestThirdId, this.ResponseThirdId, _requestBody, responseBody);

                    if (IsCipher)
                    {
                        log.RequestContent = _requestCipher;
                        log.ResponseContent = responseCipher;
                    }

                    var responseContent = JsonConvert.SerializeObject(new ResultData<string>()
                    {
                        IsSuccess = result?.IsSuccess ?? false,
                        Data = log.ResponseContent,
                        Message = result?.Message ?? string.Empty,
                    });


                    log.ResponseContent = responseContent;

                    var db = AppSession.CurrentDb.Value;
                    db.Add(log);
                }
            }
            catch (Exception ex)
            {
                var error = ex;
            }

            context.Result = new ObjectResult(new ResultData<string>()
            {
                IsSuccess = result?.IsSuccess ?? false,
                Data = responseCipher,
                Message = result?.Message ?? string.Empty,
            });

            base.OnActionExecuted(context);
        }

    }
}
